package main;

import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import javax.swing.ImageIcon;

import etc.Parser;

import runner.Enemy;
import runner.EnemyTemplate;
import towers.Tower;

public class GameMaster implements Tickable, Observer {
	private static final int WAVE_WAIT=500;
	private static final int ENEMY_WAIT=40;
	private static final int ENEMY_COUNT=10;
	
	private TDMap map;
	private Ticker ticker;
	private Set<Enemy> enemies;
	private PlayerStats ps;
	private Logger logger;
	private List<EnemyTemplate> etemplates;

	public GameMaster(TDMap map, Ticker ticker, PlayerStats ps, Logger logg) {
		this.map = map;
		this.ticker = ticker;
		this.ps = ps;
		this.logger = logg;
		map.addObserver(this);
		enemies = new HashSet<Enemy>();
		ticker.addTickable(this);
		map.setEnemies(enemies);
		etemplates = Parser.getEnemies();
	}
	
	private int counter=0;
	private int sent=0;
	private boolean inwave=true;
	
	@Override
	public void tick() {
		if (inwave) {
			counter = (counter+1)%ENEMY_WAIT;
			if (counter == 0) {
				int enemlev= ps.level>=etemplates.size()?etemplates.size()-1: ps.level;
				Enemy e = new Enemy(map, map.getPath().get(0).clone(), etemplates.get(enemlev));
				enemies.add(e);
				e.addObserver(this);
				map.addObserver(e);
				ticker.addTickable(e);
				sent++;
				if (sent >= ENEMY_COUNT) {
					sent=0;
					inwave=false;
					ps.level++;
					logger.add("Next wave is \""+ etemplates.get(enemlev).name +"\" in "+ WAVE_WAIT +" ticks");
					ps.upd();
				}
			}
		} else {
			++counter;
			if (counter == WAVE_WAIT) {
				inwave=true;
				counter=0;
			}
		}
	}

	public Set<Enemy> getEnemies() {
		return enemies;
	}

	@Override
	public void update(Observable obs, Object arg1) {
		if (obs instanceof TDMap) {
			TDMap td = (TDMap)obs;
			Set<Tower> towers = new HashSet<Tower>(td.getTowerMap().values());
			ticker.add(towers);
		} else if (obs instanceof Enemy){
			Enemy e = (Enemy)obs;
			if (e.isDead()) {
				ps.cash += e.getTemplate().bounty;
				ps.upd();
				enemies.remove(e);
			} else if (e.finished()) {
				ps.lives--;
				ps.upd();
				enemies.remove(e);
			}
		}
	}
}
